/*
 * Copyright (C) 2023 KylinSoftCo., Ltd.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
 *
**/
#include "serviceinterface.h"
#include <QDBusConnection>
#include <QSettings>
#include <QDir>
#include <QRegExp>
#include <QFile>
#include <QTimer>
#include <pwd.h>
#include <unistd.h>
#include <sys/types.h>
#include <QFileSystemWatcher>
#include <QDebug>
#include <QProcess>
#include <QDBusPendingReply>
#include <QDBusMetaType>
#include <QDBusConnectionInterface>
#include <QDBusContext>
#include <QDBusInterface>
#include <QDBusMessage>
#include "servicemanager.h"
#include "personalizeddata.h"
#include <unistd.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>

#define UKUI_GREETER        "/usr/sbin/ukui-greeter"
#define UKUI_SCREENSAVER    "/usr/bin/ukui-screensaver-backend"

#define GREETER_DBUS_PATH           "/"
#define GREETER_DBUS_INTERFACE      "org.ukui.greeter"
#define SCREENSAVER_DBUS_PATH       "/"
#define SCREENSAVER_DBUS_INTERFACE  "org.ukui.screensaver"
#define COMM_CONFIG_PATH "/etc/biometric-auth/ukui-biometric.conf"
#define USER_CONFIG_PATH "/home/%1/.biometric_auth/ukui_biometric.conf"
#define OLD_990_USER_CONFIG_PATH "/home/%1/.biometric-auth/ukui-biometric.conf"
#define PROC_CPUINFO "/proc/cpuinfo"

ServiceInterface::ServiceInterface()
{
    bool res = QDBusConnection::systemBus().registerService("org.ukui.UniauthBackend");
    if(!res){
        qInfo()<<"registerService org.ukui.UniauthBackend failed!!";
        exit(0);
    }
    res = QDBusConnection::systemBus().registerObject("/org/ukui/UniauthBackend", "org.ukui.UniauthBackend",
                                                      this, QDBusConnection::ExportAllSlots|QDBusConnection::ExportAllSignals);
    if(!res){
        qInfo()<<"registerObject /org/ukui/UniauthBackend failed!!";
        exit(0);
    }

    registerCustomTypes();
    checkIs990();
    m_serviceInterface = new QDBusInterface(DBUS_SERVICE, DBUS_PATH,
                                            DBUS_INTERFACE,
                                            QDBusConnection::systemBus(), this);

    m_serviceInterface->setTimeout(2147483647);
    connect(m_serviceInterface, SIGNAL(USBDeviceHotPlug(int, int, int)),
            this, SLOT(onUSBDeviceHotPlug(int,int,int)));
    updateCommDefaultDevice(-1);
    initData();

    ServiceManager *sm = ServiceManager::instance();
    connect(sm, &ServiceManager::serviceStatusChanged,
            this, &ServiceInterface::onBiometricDbusChanged);

    rsac.generateKeyPair(priKey, pubKey, 1024);
    connect(KYLINUSERDATAMNG::getInstance(), &PersonalizedDataMng::conf_changed, this, &ServiceInterface::updateUserInformation);
}

void ServiceInterface::setDefaultDevice(QString userName, int bioDevType, QString deviceName)
{
    QString configPath = QString(USER_CONFIG_PATH).arg(userName);
    qDebug() << configPath << bioDevType ;
    QSettings settings(configPath, QSettings::IniFormat);
    switch (bioDevType) {
    case BIOTYPE_FACE:
        settings.setValue("FC_DefaultDevice", deviceName);
        break;
    case BIOTYPE_FINGERPRINT:
        settings.setValue("FP_DefaultDevice", deviceName);
        break;
    case BIOTYPE_FINGERVEIN:
        settings.setValue("FV_DefaultDevice", deviceName);
        break;
    case BIOTYPE_IRIS:
        settings.setValue("IR_DefaultDevice", deviceName);
        break;
    case BIOTYPE_VOICEPRINT:
        settings.setValue("VP_DefaultDevice", deviceName);
        break;
    case UNIT_GENERAL_UKEY:
        settings.setValue("GU_DefaultDevice",deviceName);
        break;
    case REMOTE_QRCODE_TYPE:
        settings.setValue("WC_DefaultDevice", deviceName);
        break;
    default:
        break;
    }
    settings.sync();
    qDebug()<<"setDefaultDevice:"<<userName<<","<<bioDevType<<","<<deviceName;
    emit defaultDeviceChanged(userName, bioDevType, deviceName);
}

void ServiceInterface::setDefaultDevice(int bioDevType, QString deviceName)
{
    QDBusConnection conn = connection();
    QDBusMessage msg = message();
    int uid = conn.interface()->serviceUid(msg.service()).value();
    struct passwd *pwinfo = getpwuid(uid);
    if (pwinfo && pwinfo->pw_name) {
        setDefaultDevice(pwinfo->pw_name, bioDevType, deviceName);
    } else {
        qInfo()<<"GetPWInfo failed!!";
    }
}

QString ServiceInterface::getDefaultDevice(QString userName, int bioDevType)
{
    QString defaultDevice = "";
    QString configPath = QString(USER_CONFIG_PATH).arg(userName);
    QSettings settings(configPath, QSettings::IniFormat);
    // 获取用户旧的默认设备
    if (settings.contains("DefaultDevice")) {
        QString strOldDefDev = settings.value("DefaultDevice").toString();
        if (!strOldDefDev.isEmpty()) {
            for (auto devInfo : m_listDeviceInfos) {
                if (devInfo && devInfo->device_shortname == strOldDefDev) {
                    QString strBioDefType = "";
                    switch(devInfo->biotype) {
                    case BIOTYPE_FINGERPRINT:
                        strBioDefType = "FP_DefaultDevice";
                        break;
                    case BIOTYPE_FINGERVEIN:
                        strBioDefType = "FV_DefaultDevice";
                        break;
                    case BIOTYPE_IRIS:
                        strBioDefType = "IR_DefaultDevice";
                        break;
                    case BIOTYPE_FACE:
                        strBioDefType = "FC_DefaultDevice";
                        break;
                    case BIOTYPE_VOICEPRINT:
                        strBioDefType = "VP_DefaultDevice";
                        break;
                    case UNIT_GENERAL_UKEY:
                        strBioDefType = "GU_DefaultDevice";
                        break;
                    case REMOTE_QRCODE_TYPE:
                        strBioDefType = "WC_DefaultDevice";
                        break;
                    default:
                        break;
                    }
                    if (!strBioDefType.isEmpty() && !settings.contains(strBioDefType)) {
                        settings.setValue(strBioDefType, strOldDefDev);
                        settings.setValue("DefaultDevice", "");
                        settings.sync();
                    }
                    if (bioDevType == devInfo->biotype) {
                        return strOldDefDev;
                    }
                    break;
                }
            }
        }
    }
    switch (bioDevType) {
    case BIOTYPE_FACE:
        defaultDevice = settings.value("FC_DefaultDevice").toString();
        break;
    case BIOTYPE_FINGERPRINT:
        defaultDevice = settings.value("FP_DefaultDevice").toString();
        break;
    case BIOTYPE_FINGERVEIN:
        defaultDevice = settings.value("FV_DefaultDevice").toString();
        break;
    case BIOTYPE_IRIS:
        defaultDevice = settings.value("IR_DefaultDevice").toString();
        break;
    case BIOTYPE_VOICEPRINT:
        defaultDevice = settings.value("VP_DefaultDevice").toString();
        break;
    case UNIT_GENERAL_UKEY:
        defaultDevice = settings.value("GU_DefaultDevice").toString();
        break;
    case REMOTE_QRCODE_TYPE:
        defaultDevice = settings.value("WC_DefaultDevice").toString();
        break;
    default:
        defaultDevice = settings.value("DefaultDevice").toString();
        break;
    }
    if(defaultDevice.isEmpty()) {
        QSettings settings2(COMM_CONFIG_PATH, QSettings::IniFormat);
        switch (bioDevType) {
        case BIOTYPE_FACE:
            defaultDevice = settings2.value("FC_DefaultDevice").toString();
            break;
        case BIOTYPE_FINGERPRINT:
            defaultDevice = settings2.value("FP_DefaultDevice").toString();
            break;
        case BIOTYPE_FINGERVEIN:
            defaultDevice = settings2.value("FV_DefaultDevice").toString();
            break;
        case BIOTYPE_IRIS:
            defaultDevice = settings2.value("IR_DefaultDevice").toString();
            break;
        case BIOTYPE_VOICEPRINT:
            defaultDevice = settings2.value("VP_DefaultDevice").toString();
            break;
        case UNIT_GENERAL_UKEY:
            defaultDevice = settings2.value("GU_DefaultDevice").toString();
            break;
        case REMOTE_QRCODE_TYPE:
            defaultDevice = settings2.value("WC_DefaultDevice").toString();
            break;
        default:
            defaultDevice = settings2.value("DefaultDevice").toString();
            break;
        }
    }
    return defaultDevice;
}

QStringList ServiceInterface::getAllDefaultDevice(QString userName)
{
    QStringList listDefDevice;
    QString configPath = QString(USER_CONFIG_PATH).arg(userName);
    QSettings settings(configPath, QSettings::IniFormat);
    int nOldDefType = -1;
    // 获取用户旧的默认设备
    if (settings.contains("DefaultDevice")) {
        QString strOldDefDev = settings.value("DefaultDevice").toString();
        if (!strOldDefDev.isEmpty()) {
            for (auto devInfo : m_listDeviceInfos) {
                if (devInfo && devInfo->device_shortname == strOldDefDev) {
                    QString strBioDefType = "";
                    switch(devInfo->biotype) {
                    case BIOTYPE_FINGERPRINT:
                        strBioDefType = "FP_DefaultDevice";
                        break;
                    case BIOTYPE_FINGERVEIN:
                        strBioDefType = "FV_DefaultDevice";
                        break;
                    case BIOTYPE_IRIS:
                        strBioDefType = "IR_DefaultDevice";
                        break;
                    case BIOTYPE_FACE:
                        strBioDefType = "FC_DefaultDevice";
                        break;
                    case BIOTYPE_VOICEPRINT:
                        strBioDefType = "VP_DefaultDevice";
                        break;
                    case UNIT_GENERAL_UKEY:
                        strBioDefType = "GU_DefaultDevice";
                        break;
                    case REMOTE_QRCODE_TYPE:
                        strBioDefType = "WC_DefaultDevice";
                        break;
                    default:
                        break;
                    }
                    if (!strBioDefType.isEmpty() && !settings.contains(strBioDefType)) {
                        nOldDefType = devInfo->biotype;
                        listDefDevice.push_back(strOldDefDev);
                        settings.setValue(strBioDefType, strOldDefDev);
                        settings.setValue("DefaultDevice", "");
                        settings.sync();
                    }
                    break;
                }
            }
        }
    }
    QSettings settings2(COMM_CONFIG_PATH, QSettings::IniFormat);
    for (int nBioType = 0; nBioType <= REMOTE_QRCODE_TYPE; nBioType++) {
        QString defaultDevice = "";
        if (nBioType == nOldDefType)
            continue;
        switch (nBioType) {
        case BIOTYPE_FACE:
            defaultDevice = settings.value("FC_DefaultDevice").toString();
            break;
        case BIOTYPE_FINGERPRINT:
            defaultDevice = settings.value("FP_DefaultDevice").toString();
            break;
        case BIOTYPE_FINGERVEIN:
            defaultDevice = settings.value("FV_DefaultDevice").toString();
            break;
        case BIOTYPE_IRIS:
            defaultDevice = settings.value("IR_DefaultDevice").toString();
            break;
        case BIOTYPE_VOICEPRINT:
            defaultDevice = settings.value("VP_DefaultDevice").toString();
            break;
        case UNIT_GENERAL_UKEY:
            defaultDevice = settings.value("GU_DefaultDevice").toString();
            break;
        case REMOTE_QRCODE_TYPE:
            defaultDevice = settings.value("WC_DefaultDevice").toString();
            break;
        default:
            break;
        }
        if(defaultDevice.isEmpty()) {
            switch (nBioType) {
            case BIOTYPE_FACE:
                defaultDevice = settings2.value("FC_DefaultDevice").toString();
                break;
            case BIOTYPE_FINGERPRINT:
                defaultDevice = settings2.value("FP_DefaultDevice").toString();
                break;
            case BIOTYPE_FINGERVEIN:
                defaultDevice = settings2.value("FV_DefaultDevice").toString();
                break;
            case BIOTYPE_IRIS:
                defaultDevice = settings2.value("IR_DefaultDevice").toString();
                break;
            case BIOTYPE_VOICEPRINT:
                defaultDevice = settings2.value("VP_DefaultDevice").toString();
                break;
            case UNIT_GENERAL_UKEY:
                defaultDevice = settings2.value("GU_DefaultDevice").toString();
                break;
            case REMOTE_QRCODE_TYPE:
                defaultDevice = settings2.value("WC_DefaultDevice").toString();
                break;
            default:
                break;
            }
        }
        if (!defaultDevice.isEmpty()) {
            listDefDevice.push_back(defaultDevice);
        }
    }
    return listDefDevice;
}

//设置通用默认设备
void ServiceInterface::setCommDefaultDevice(int bioDevType, QString deviceName)
{
    QSettings settings(COMM_CONFIG_PATH, QSettings::IniFormat);
    switch (bioDevType) {
    case BIOTYPE_FACE:
        settings.setValue("FC_DefaultDevice", deviceName);
        break;
    case BIOTYPE_FINGERPRINT:
        settings.setValue("FP_DefaultDevice", deviceName);
        break;
    case BIOTYPE_FINGERVEIN:
        settings.setValue("FV_DefaultDevice", deviceName);
        break;
    case BIOTYPE_IRIS:
        settings.setValue("IR_DefaultDevice", deviceName);
        break;
    case BIOTYPE_VOICEPRINT:
        settings.setValue("VP_DefaultDevice", deviceName);
        break;
    case UNIT_GENERAL_UKEY:
        settings.setValue("GU_DefaultDevice", deviceName);
        break;
    case REMOTE_QRCODE_TYPE:
        settings.setValue("WC_DefaultDevice", deviceName);
        break;
    default:
        break;
    }
    settings.sync();
    qDebug()<<"setCommDefaultDevice:"<<bioDevType<<","<<deviceName;
    emit defaultDeviceChanged("", bioDevType, deviceName);
}

//获取通用默认设备
QString ServiceInterface::getCommDefaultDevice(int bioDevType)
{
    QString defaultDevice = "";
    QSettings settings2(COMM_CONFIG_PATH, QSettings::IniFormat);
    switch (bioDevType) {
    case BIOTYPE_FACE:
        defaultDevice = settings2.value("FC_DefaultDevice").toString();
        break;
    case BIOTYPE_FINGERPRINT:
        defaultDevice = settings2.value("FP_DefaultDevice").toString();
        break;
    case BIOTYPE_FINGERVEIN:
        defaultDevice = settings2.value("FV_DefaultDevice").toString();
        break;
    case BIOTYPE_IRIS:
        defaultDevice = settings2.value("IR_DefaultDevice").toString();
        break;
    case BIOTYPE_VOICEPRINT:
        defaultDevice = settings2.value("VP_DefaultDevice").toString();
        break;
    case UNIT_GENERAL_UKEY:
        defaultDevice = settings2.value("GU_DefaultDevice").toString();
        break;
    case REMOTE_QRCODE_TYPE:
        defaultDevice = settings2.value("WC_DefaultDevice").toString();
        break;
    default:
        defaultDevice = settings2.value("DefaultDevice").toString();
        break;
    }
    return defaultDevice;
}

void ServiceInterface::setBioAuthStatus(int bioAuthType, bool status)
{
    QDBusConnection conn = connection();
    QDBusMessage msg = message();
    int uid = conn.interface()->serviceUid(msg.service()).value();
    struct passwd *pwinfo = getpwuid(uid);
    if (pwinfo && pwinfo->pw_name) {
        QString configPath = QString(USER_CONFIG_PATH).arg(pwinfo->pw_name);
        QSettings settings(configPath, QSettings::IniFormat);
        switch (bioAuthType) {
        case ENABLETYPE_BIO:
            settings.setValue("EnableAuth", status);
            break;
        case ENABLETYPE_SAVER:
            settings.setValue("SaverEnable", status);
            break;
        case ENABLETYPE_GREETER:
            settings.setValue("GreeterEnable", status);
            break;
        case ENABLETYPE_POLKIT:
            settings.setValue("PolkitEnable", status);
            break;
        case ENABLETYPE_SU:
            settings.setValue("SuEnable", status);
            break;
        case ENABLETYPE_SUDO:
            settings.setValue("SudoEnable", status);
            break;
        case ENABLETYPE_LOGIN:
            settings.setValue("LoginEnable", status);
            break;
        default:
            break;
        }
        settings.sync();
        emit bioAuthStatusChanged(pwinfo->pw_name, bioAuthType, status);
        qDebug()<<"setBioAuthStatus:"<<pwinfo->pw_name<<","<<bioAuthType<<","<<status;
    } else {
        qInfo()<<"GetPWInfo failed!!";
    }
}

bool ServiceInterface::getBioAuthStatus(QString userName, int bioAuthType)
{
    QString configPath = QString(USER_CONFIG_PATH).arg(userName);
    QSettings settings(configPath, QSettings::IniFormat);
    QString strBioAuthType = "";
    switch (bioAuthType) {
    case ENABLETYPE_BIO:
        strBioAuthType = "EnableAuth";
        break;
    case ENABLETYPE_SAVER:
        strBioAuthType = "SaverEnable";
        break;
    case ENABLETYPE_GREETER:
        strBioAuthType = "GreeterEnable";
        break;
    case ENABLETYPE_POLKIT:
        strBioAuthType = "PolkitEnable";
        break;
    case ENABLETYPE_SU:
        strBioAuthType = "SuEnable";
        break;
    case ENABLETYPE_SUDO:
        strBioAuthType = "SudoEnable";
        break;
    case ENABLETYPE_LOGIN:
        strBioAuthType = "LoginEnable";
        break;
    default:
        return false;
    }

    //同步990旧的配置文件，然后删除
    if(getIs990() && (bioAuthType == ENABLETYPE_BIO)){
        QString oldConfigPath = QString(OLD_990_USER_CONFIG_PATH).arg(userName);
        QSettings oldSettings(oldConfigPath, QSettings::IniFormat);
        if(oldSettings.contains(strBioAuthType)){
            settings.setValue(strBioAuthType,oldSettings.value(strBioAuthType).toBool());
            oldSettings.remove(strBioAuthType);
            oldSettings.sync();
        }
    }
    if (settings.contains(strBioAuthType)) {
        return settings.value(strBioAuthType).toBool();
    }else if(getIs990() && (bioAuthType == ENABLETYPE_BIO)){
        //990默认为打开
        return true;
    } else {
        QSettings settings2(COMM_CONFIG_PATH, QSettings::IniFormat);
        if (settings2.contains(strBioAuthType)) {
            return settings2.value(strBioAuthType).toBool();
        } else {
            return true;
        }
    }
}

int ServiceInterface::getMaxFailedTimes()
{
    QSettings sysSettings(COMM_CONFIG_PATH, QSettings::IniFormat);
    if(sysSettings.contains("MaxFailedTimes"))
        return sysSettings.value("MaxFailedTimes").toInt();
    else
        return 3;
}

int ServiceInterface::getFTimeoutTimes()
{
    QSettings sysSettings(COMM_CONFIG_PATH, QSettings::IniFormat);
    if(sysSettings.contains("FaceTimeoutTimes"))
        return sysSettings.value("FaceTimeoutTimes").toInt();
    else
        return 1;
}

void ServiceInterface::setFTimeoutTimes(int times)
{
    if (times < 1)
        times = 1;
    QSettings settings(COMM_CONFIG_PATH, QSettings::IniFormat);
    settings.setValue("FaceTimeoutTimes", times);
}

bool ServiceInterface::getQRCodeEnable()
{
    bool isEnable = false;
    QSettings sysSettings(COMM_CONFIG_PATH, QSettings::IniFormat);
    sysSettings.beginGroup("Functions");
    if (sysSettings.allKeys().contains("EnableQRCode")) {
        isEnable = sysSettings.value("EnableQRCode").toBool();
    }
    sysSettings.endGroup();
    return isEnable;
}

// 获取是否双认证
bool ServiceInterface::getDoubleAuth()
{
    QSettings sysSettings(COMM_CONFIG_PATH, QSettings::IniFormat);
    if(sysSettings.contains("DoubleAuth"))
        return sysSettings.value("DoubleAuth").toBool();
    else
        return false;
}

// 获取用户绑定
bool ServiceInterface::getUserBind()
{
    QSettings sysSettings(COMM_CONFIG_PATH, QSettings::IniFormat);
    if(sysSettings.contains("UserBind"))
        return sysSettings.value("UserBind").toBool();
    else
        return false;
}

// 获取是否在控制面板显示
bool ServiceInterface::getIsShownInControlCenter()
{
    QSettings sysSettings(COMM_CONFIG_PATH, QSettings::IniFormat);
    if(sysSettings.contains("isShownInControlCenter"))
        return sysSettings.value("isShownInControlCenter").toBool();
    else
        return false;
}

// 获取是否使用第一个设备
bool ServiceInterface::getUseFirstDevice()
{
    QSettings sysSettings(COMM_CONFIG_PATH, QSettings::IniFormat);
    if(sysSettings.contains("UseFirstDevice"))
        return sysSettings.value("UseFirstDevice").toBool();
    else
        return false;
}

// 获取是否隐藏切换按钮
bool ServiceInterface::getHiddenSwitchButton()
{
    QSettings sysSettings(COMM_CONFIG_PATH, QSettings::IniFormat);
    if(sysSettings.contains("HiddenSwitchButton"))
        return sysSettings.value("HiddenSwitchButton").toBool();
    else
        return false;
}

// 获取旧版app使能值
int ServiceInterface::getOldAppStatus()
{
    QSettings sysSettings(COMM_CONFIG_PATH, QSettings::IniFormat);
    if(sysSettings.contains("EnableAuthApp"))
        return sysSettings.value("EnableAuthApp").toInt();
    else
        return 63;
}

void ServiceInterface::onUSBDeviceHotPlug(int drvid, int action, int deviceNum)
{
    if (action > 0) {
        qDebug()<<"onUSBDeviceHotPlug in:"<<drvid;
        updateCommDefaultDevice(drvid);
    }
}

//记录当前生物认证信息
void ServiceInterface::recordAuthDrive(QString appName,int drvid,bool insert)
{
    if(insert){
        m_AuthingDriveList.insert(appName,drvid);
    }else{
        m_AuthingDriveList.remove(appName);
    }
}


//获取当前正在认证的应用
QStringList ServiceInterface::getAllAuthApp()
{
    return m_AuthingDriveList.keys();
}

//根据应用名称获取认证的驱动
int ServiceInterface::getAppAuthDrive(QString appName)
{
    if(m_AuthingDriveList.contains(appName)){
        return m_AuthingDriveList.value(appName);
    }
    return -1;
}

QString ServiceInterface::GetUserInformation(QString username)
{
    KyInfo() << username;
    return KYLINUSERDATAMNG::getInstance()->GetConfInformation(username);
}

void ServiceInterface::SetLoginSynInformation(QString val)
{
    KyInfo() << val;
    KYLINUSERDATAMNG::getInstance()->SetLoginSynInformation(val);
}

void ServiceInterface::waitBiometricServiceStatus()
{
    qDebug()<<"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~` get biometric status";
    QDBusInterface iface("org.freedesktop.systemd1", "/org/freedesktop/systemd1",
                         "org.freedesktop.systemd1.Manager",QDBusConnection::systemBus());

    QDBusReply<QDBusObjectPath> bioPath = iface.call("GetUnit","biometric-authentication.service");
    if(!bioPath.isValid()){
        return ;
    }

    QDBusInterface bioface("org.freedesktop.systemd1", bioPath.value().path(),
                           "org.freedesktop.DBus.Properties", QDBusConnection::systemBus());
    QDBusReply<QDBusVariant> sessionReply = bioface.call("Get", "org.freedesktop.systemd1.Unit", "UnitFileState");
    if(!sessionReply.isValid())
        qWarning() << sessionReply.error();
    else {
        QString res = sessionReply.value().variant().toString();
        if(res == "disable")
            return;
    }

    qDebug()<<"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~   get activeState";
    int times = 0;
    while(times<20){
        QDBusReply<QDBusVariant> sessionReply = bioface.call("Get", "org.freedesktop.systemd1.Unit", "ActiveState");
        if(!sessionReply.isValid()){
            qWarning() << sessionReply.error();
            return ;
        }
        else {
            QString res = sessionReply.value().variant().toString();
            if(res == "activating"){
                times ++;
                usleep(100000);
            }else{
                break;
            }
        }
    }
    qDebug()<<"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ times = "<<times;
}

void ServiceInterface::updateCommDefaultDevice(int nDriId)
{
    if (!m_serviceInterface) {
        return ;
    }
    QVariant variant;
    QDBusArgument argument;
    QList<QDBusVariant> qlist;
    QDBusVariant item;
    DeviceInfoPtr deviceInfo = nullptr;

    /* 返回值为 i -- int 和 av -- array of variant */
    QDBusPendingReply<int, QList<QDBusVariant> > reply = m_serviceInterface->call("GetDrvList");
    reply.waitForFinished();
    if (reply.isError()) {
        qDebug() << "GUI:" << reply.error();
        deviceCount = 0;
        return;
    }

    /* 解析 DBus 返回值，reply 有两个返回值，都是 QVariant 类型 */
    variant = reply.argumentAt(0); /* 得到第一个返回值 */
    deviceCount = variant.value<int>(); /* 解封装得到设备个数 */
    variant = reply.argumentAt(1); /* 得到第二个返回值 */
    argument = variant.value<QDBusArgument>(); /* 解封装，获取QDBusArgument对象 */
    argument >> qlist; /* 使用运算符重载提取 argument 对象里面存储的列表对象 */

    if (nDriId != -1) { // 指定设备接入
        for (int i = 0; i < deviceCount; i++) {
            item = qlist[i]; /* 取出一个元素 */
            variant = item.variant(); /* 转为普通QVariant对象 */
            /* 解封装得到 QDBusArgument 对象 */
            argument = variant.value<QDBusArgument>();
            deviceInfo = std::make_shared<DeviceInfo>();
            argument >> *deviceInfo; /* 提取最终的 DeviceInfo 结构体 */
            if (nDriId == deviceInfo->device_id) {
                if (getCommDefaultDevice(deviceInfo->biotype).isEmpty()) {
                    setCommDefaultDevice(deviceInfo->biotype, deviceInfo->device_shortname);
                }
                break;
            }
        }
    } else {
        m_listDeviceInfos.clear();
        for (int i = 0; i < deviceCount; i++) {
            item = qlist[i]; /* 取出一个元素 */
            variant = item.variant(); /* 转为普通QVariant对象 */
            /* 解封装得到 QDBusArgument 对象 */
            argument = variant.value<QDBusArgument>();
            deviceInfo = std::make_shared<DeviceInfo>();
            argument >> *deviceInfo; /* 提取最终的 DeviceInfo 结构体 */
            m_listDeviceInfos.push_back(deviceInfo);
        }
    }
}

void ServiceInterface::initData()
{
    // 沿用旧app enable
    QSettings sysSettings(COMM_CONFIG_PATH, QSettings::IniFormat);
    if(sysSettings.contains("EnableAuthApp") || sysSettings.contains("Functions/EnableAuthApp")) {
        int nAppOldStatus = 0;
        if (sysSettings.contains("Functions/EnableAuthApp")) {
            nAppOldStatus = sysSettings.value("Functions/EnableAuthApp").toInt();
        } else {
            nAppOldStatus = sysSettings.value("EnableAuthApp").toInt();
        }
        if ((nAppOldStatus&0x01) && !sysSettings.contains("GreeterEnable")) { // greeter
            sysSettings.setValue("GreeterEnable", true);
        }
        if ((nAppOldStatus&0x02) && !sysSettings.contains("SaverEnable")) { // saver
            sysSettings.setValue("SaverEnable", true);
        }
        if ((nAppOldStatus&0x04) && !sysSettings.contains("PolkitEnable")) { // polkit
            sysSettings.setValue("PolkitEnable", true);
        }
        if ((nAppOldStatus&0x08) && !sysSettings.contains("SudoEnable")) { // sudo
            sysSettings.setValue("SudoEnable", true);
        }
        if ((nAppOldStatus&0x10) && !sysSettings.contains("SuEnable")) { // su
            sysSettings.setValue("SuEnable", true);
        }
        if ((nAppOldStatus&0x20) && !sysSettings.contains("LoginEnable")) { // login
            sysSettings.setValue("LoginEnable", true);
        }
    }
    // 沿用旧的默认设备
    if(sysSettings.contains("DefaultDevice")) {
        QString strOldDefDev = sysSettings.value("DefaultDevice").toString();
        if (!strOldDefDev.isEmpty()) {
            for (auto devInfo : m_listDeviceInfos) {
                if (devInfo && devInfo->device_shortname == strOldDefDev) {
                    QString strBioDefType = "";
                    switch(devInfo->biotype) {
                    case BIOTYPE_FINGERPRINT:
                        strBioDefType = "FP_DefaultDevice";
                        break;
                    case BIOTYPE_FINGERVEIN:
                        strBioDefType = "FV_DefaultDevice";
                        break;
                    case BIOTYPE_IRIS:
                        strBioDefType = "IR_DefaultDevice";
                        break;
                    case BIOTYPE_FACE:
                        strBioDefType = "FC_DefaultDevice";
                        break;
                    case BIOTYPE_VOICEPRINT:
                        strBioDefType = "VP_DefaultDevice";
                        break;
                    case UNIT_GENERAL_UKEY:
                        strBioDefType = "GU_DefaultDevice";
                        break;
                    case REMOTE_QRCODE_TYPE:
                        strBioDefType = "WC_DefaultDevice";
                        break;
                    default:
                        break;
                    }
                    if (!strBioDefType.isEmpty() && !sysSettings.contains(strBioDefType)) {
                        sysSettings.setValue(strBioDefType, strOldDefDev);
                        sysSettings.setValue("DefaultDevice", "");
                    }
                    break;
                }
            }
        }
    }
    // 设置未设置过默认设备的类型，如果驱动已打开且已连接
    for (auto devInfo : m_listDeviceInfos) {
        if (devInfo && devInfo->device_available > 0 && devInfo->driver_enable > 0) {
            QString strBioDefType = "";
            switch(devInfo->biotype) {
            case BIOTYPE_FINGERPRINT:
                strBioDefType = "FP_DefaultDevice";
                break;
            case BIOTYPE_FINGERVEIN:
                strBioDefType = "FV_DefaultDevice";
                break;
            case BIOTYPE_IRIS:
                strBioDefType = "IR_DefaultDevice";
                break;
            case BIOTYPE_FACE:
                strBioDefType = "FC_DefaultDevice";
                break;
            case BIOTYPE_VOICEPRINT:
                strBioDefType = "VP_DefaultDevice";
                break;
            case UNIT_GENERAL_UKEY:
                strBioDefType = "GU_DefaultDevice";
                break;
            case REMOTE_QRCODE_TYPE:
                strBioDefType = "WC_DefaultDevice";
                break;
            default:
                break;
            }
            if (!strBioDefType.isEmpty() && !sysSettings.contains(strBioDefType)) {
                sysSettings.setValue(strBioDefType, devInfo->device_shortname);
            }
        }
    }
    sysSettings.sync();
}

void ServiceInterface::onBiometricDbusChanged(bool bActive)
{
    qDebug()<<"BiometricDbus:"<<bActive;
    if (bActive) {
        updateCommDefaultDevice(-1);
        initData();
    }
}

void ServiceInterface::checkIs990()
{
    QRegExp  r1("kirin.*9.0");
    r1.setCaseSensitivity(Qt::CaseInsensitive);
    QRegExp r2("pangu.*m900");
    r2.setCaseSensitivity(Qt::CaseInsensitive);

    QFile file(PROC_CPUINFO);
    if(!file.exists()){
        is990 = false;
    }
    file.open(QFile::ReadOnly);
    QString str(file.readAll());
    is990 = (str.contains(r1) || str.contains(r2));
    file.close();
}

bool ServiceInterface::getIs990()
{
    return is990;
}

QString ServiceInterface::getPublicEncrypt()
{
    return pubKey;
}

bool ServiceInterface::sendPassword(QString username,QByteArray password)
{
    QByteArray decryptText;
    QByteArray encryptText;
    rsac.decrypt(password, decryptText, priKey);     // 解密
    //如果处于登录状态

    qDebug()<<"sendPassword"<<loginAppList.count()<<loginAppList;
    if(loginAppList.contains("lightdm")){
        qDebug()<<"login:";
        isFirstLogin = false;
        QString publicKey = getLoginPubKey(loginAppList.value("lightdm"),SCREENSAVER_DBUS_PATH,SCREENSAVER_DBUS_INTERFACE);
        rsac.encrypt(decryptText, encryptText, publicKey.toLatin1());
        return sendLoginPassword(loginAppList.value("lightdm"),SCREENSAVER_DBUS_PATH,SCREENSAVER_DBUS_INTERFACE,username,encryptText);
    }

    //处于锁屏状态
    if(loginAppList.contains(username)){
        qDebug()<<"unlock:";
        isFirstLogin = false;
        QString publicKey = getLoginPubKey(loginAppList.value(username),SCREENSAVER_DBUS_PATH,SCREENSAVER_DBUS_INTERFACE);
        rsac.encrypt(decryptText, encryptText, publicKey.toLatin1());
        return sendLoginPassword(loginAppList.value(username),SCREENSAVER_DBUS_PATH,SCREENSAVER_DBUS_INTERFACE,username,encryptText);
    }

    if(loginAppList.count()>0){
	qDebug()<<"login by screensaver:";
	isFirstLogin = false;
        QString publicKey = getLoginPubKey(loginAppList.value(loginAppList.firstKey()),SCREENSAVER_DBUS_PATH,SCREENSAVER_DBUS_INTERFACE);
        rsac.encrypt(decryptText, encryptText, publicKey.toLatin1());
        return sendLoginPassword(loginAppList.value(loginAppList.firstKey()),SCREENSAVER_DBUS_PATH,SCREENSAVER_DBUS_INTERFACE,username,encryptText);
    }

    //如果是第一次调用，则配置自动登录
    if(isFirstLogin){
        qDebug()<<"isFirstLogin:";
        isFirstLogin = false;
        hasSaveLogin = true;
        return handleFirstSingleLogn(username,decryptText);
    }

    isFirstLogin = false;
    return false;
}

bool ServiceInterface::handleFirstSingleLogn(QString username,QByteArray decryptText)
{
     QEventLoop loopTemp;
     bool ret = false;
     QByteArray encryptText;

     qDebug()<<"handleFirstSingleLogn wait";
     QMetaObject::Connection connection = QObject::connect(this, &ServiceInterface::onLoginServicdRegisted, [&loopTemp]() {
         if (loopTemp.isRunning()) {
             loopTemp.quit();
         }
     });
     QTimer::singleShot(10000, &loopTemp, SLOT(quit()));
     loopTemp.exec();
     qDebug()<<"handleFirstSingleLogn finished";
     disconnect(connection);
     qDebug()<<loginAppList.count();
     if(loginAppList.contains("lightdm")){
         isFirstLogin = false;
         QString publicKey = getLoginPubKey(loginAppList.value("lightdm"),SCREENSAVER_DBUS_PATH,SCREENSAVER_DBUS_INTERFACE);
         if(publicKey.isEmpty()){
             qDebug()<<"get Login PubKey failed!";
             return false;
         }
         rsac.encrypt(decryptText, encryptText, publicKey.toLatin1());
         return sendLoginPassword(loginAppList.value("lightdm"),SCREENSAVER_DBUS_PATH,SCREENSAVER_DBUS_INTERFACE,username,encryptText);
     }
     return ret;
}

QString  ServiceInterface::getLoginPubKey(QString service,QString path,QString interface)
{
    QDBusInterface iface(service,
                             path,
                             interface,
                             QDBusConnection::systemBus());
    QDBusReply<QString> stateReply = iface.call("getPublicEncrypt");

    if(!stateReply.isValid()){
        qWarning()<< "Get state error:" << stateReply.error();
        qDebug()<<"getPublicEncrypt failed";
        return "";
    }
    return stateReply.value();
}

bool ServiceInterface::sendSignalLoginFinished(QString username,bool res)
{
    qDebug()<<"sendSignalLoginFinished "<<username<<res;
    emit onSignalLoginFinished(username,res);

    return true;
}

bool  ServiceInterface::sendLoginPassword(QString service,QString path,QString interface,QString username,QByteArray array)
{
    QEventLoop loopTemp;
    bool ret = false;

    qDebug()<<"sendLoginPassword";
    QMetaObject::Connection connection = QObject::connect(this, &ServiceInterface::onSignalLoginFinished, [&loopTemp,&ret](QString username,bool res) {
        qDebug()<<"onSignalLoginFinished:"<<username<<res;
        ret = res;
        if (loopTemp.isRunning()) {
                loopTemp.quit();
        }
    });

    QDBusInterface iface(service,
                         path,
                         interface,
                         QDBusConnection::systemBus());
    QDBusReply<bool> stateReply = iface.call("sendPassword",username,array);
    if(!stateReply.isValid()){
        disconnect(connection);
        return false;
    }

    if(!stateReply.value()){
        disconnect(connection);
        return stateReply.value();
    }

    QTimer::singleShot(30000, &loopTemp, SLOT(quit()));

    loopTemp.exec();
    disconnect(connection);

    return ret;
}
QString ServiceInterface::getProcessNameFromPid(int pid)
{
    QString filename = "/proc/" + QString::number(pid) + "/cmdline";
    qDebug()<<"filename is "<<filename;
    QFile file(filename);
    if(!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        qDebug()<<"Can't open the file!"<<endl;
        return "";
    }
    QByteArray text = file.readAll();
    return QString(text);
}

QString ServiceInterface::getUserNameFromUid(int uid)
{
    struct passwd *pw = NULL;
    pw = getpwuid(uid);
    if(pw){
        return QString(pw->pw_name);
    }
    return "";
}

void ServiceInterface::onDbusNameOwnerChanged(QString name,QString oldOwner,QString newOwner)
{
    if(newOwner.isEmpty()){
        for(QString str:loginAppList.keys()){
            if(name == loginAppList.value(str)){
                qDebug()<<"remove name  "<<name;
                loginAppList.remove(str);
            }
        }
    }
}

bool ServiceInterface::registerLoginApp()
{
    QDBusConnection conn = connection();
    QDBusMessage msg = message();

    qDebug() << "Sender Name" << conn.interface()->serviceOwner(msg.service()).value();
    qDebug() << "Sender Pid " << conn.interface()->servicePid(msg.service()).value();
    qDebug() << "Sender uid " << conn.interface()->serviceUid(msg.service()).value();

    int pid = conn.interface()->servicePid(msg.service()).value();
    QString serviceOwner = conn.interface()->serviceOwner(msg.service()).value();
    int uid = conn.interface()->serviceUid(msg.service()).value();

    QString appName = getProcessNameFromPid(pid);
    qDebug()<<"appName = "<<appName;

    if(appName != UKUI_GREETER && appName != UKUI_SCREENSAVER){
        return false;
    }

    QString appUser = getUserNameFromUid(uid);
    if(appUser.isEmpty())
        return false;

    qDebug()<<"insert "<<appUser<<serviceOwner;
    loginAppList.insert(appUser,serviceOwner);

    if(appUser == "lightdm" && hasSaveLogin){
        QTimer::singleShot(1000, this, [=](){
           emit onLoginServicdRegisted();
        });
    }

    return true;
}

